package cn.com.bluemoon.daps.model.core.file.entry;

import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.model.core.file.transformer.ImportEntryTableDto;
import cn.com.bluemoon.daps.model.entity.DapDataModelSubordinateKey;
import cn.com.bluemoon.daps.model.entity.DapDataModelTable;
import cn.com.bluemoon.daps.model.entity.DapDataModelTableField;
import cn.com.bluemoon.daps.model.entity.DapDataModelTablePartition;
import cn.com.bluemoon.daps.model.service.DapDataModelSubordinateKeyService;
import cn.com.bluemoon.daps.model.service.DapDataModelTableFieldService;
import cn.com.bluemoon.daps.model.service.DapDataModelTablePartitionService;
import cn.com.bluemoon.daps.model.service.DapDataModelTableService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Jarod.Kong
 * @date 2021/3/18 11:05
 */
@Service
@Slf4j
public class MultiEntryImpl implements MultiEntry<ImportEntryTableDto> {
    /**
     * 数据集分片大小
     */
    private static final int DATA_SHARE_SIZE = 500;
    /**
     * 分片后入库的批量大小
     */
    private static final int MINI_BATCH_SIZE = 1000;
    @Resource
    private DapDataModelTableService tableService;
    @Resource
    private DapDataModelTableFieldService fieldService;
    @Resource
    private DapDataModelSubordinateKeyService indexService;
    @Resource
    private DapDataModelTablePartitionService partitionService;

    /**
     * 分片，并行入库
     *
     * @param entryModels x
     * @return result
     */
    @Override
    public ResultBean<Boolean> mutilEntry(List<ImportEntryTableDto> entryModels) {
        if (entryModels == null || entryModels.isEmpty()) {
            return ResultBean.ok(true);
        }
        List<List<ImportEntryTableDto>> batchList = Lists.partition(entryModels, DATA_SHARE_SIZE);
        batchList.parallelStream().forEach(this::miniBatchSubmit);
        log.info("写入所有数据完成，size:{}", entryModels.size());
        return ResultBean.ok(true);
    }

    /**
     * 分片后的入库
     *
     * @param shareTbs 分片
     */
    private void miniBatchSubmit(List<ImportEntryTableDto> shareTbs) {
        final List<DapDataModelTable> tablesBatch = new ArrayList<>(MINI_BATCH_SIZE);
        final List<DapDataModelTableField> fieldsBatch = new ArrayList<>(MINI_BATCH_SIZE);
        final List<DapDataModelSubordinateKey> indexesBatch = new ArrayList<>(MINI_BATCH_SIZE);
        final List<DapDataModelTablePartition> partitionsBatch = new ArrayList<>(MINI_BATCH_SIZE);
        for (ImportEntryTableDto entryModel : shareTbs) {
            DapDataModelTable table = entryModel.getTable();
            tablesBatch.add(table);
            if (tablesBatch.size() >= MINI_BATCH_SIZE) {
                submitTables(tablesBatch);
            }

            List<DapDataModelTableField> fields = entryModel.getFields();
            fieldsBatch.addAll(fields);
            if (fieldsBatch.size() >= MINI_BATCH_SIZE) {
                submitFields(fieldsBatch);
            }

            List<DapDataModelSubordinateKey> indexes = entryModel.getIndexes();
            indexesBatch.addAll(indexes);
            if (indexesBatch.size() >= MINI_BATCH_SIZE) {
                submitIndexes(indexesBatch);
            }

            List<DapDataModelTablePartition> partitions = entryModel.getPartitions();
            partitionsBatch.addAll(partitions);
            if (partitionsBatch.size() >= MINI_BATCH_SIZE) {
                submitPartitions(partitionsBatch);
            }
        }
        submitTables(tablesBatch);
        submitFields(fieldsBatch);
        submitIndexes(indexesBatch);
        submitPartitions(partitionsBatch);
    }

    private void submitPartitions(List<DapDataModelTablePartition> partitionsBatch) {
        boolean batch = partitionService.bmSaveBatch(partitionsBatch);
        log.info("批次提交，size:{}，status:{}", partitionsBatch.size(), batch);
        partitionsBatch.clear();
    }

    private void submitIndexes(List<DapDataModelSubordinateKey> indexesBatch) {
        boolean batch = indexService.bmSaveBatch(indexesBatch);
        log.info("批次提交，size:{}，status:{}", indexesBatch.size(), batch);
        indexesBatch.clear();
    }

    private void submitFields(List<DapDataModelTableField> fieldsBatch) {
        boolean batch = fieldService.bmSaveBatch(fieldsBatch);
        log.info("批次提交，size:{}，status:{}", fieldsBatch.size(), batch);
        fieldsBatch.clear();
    }

    private void submitTables(List<DapDataModelTable> tablesBatch) {
        boolean batch = tableService.bmSaveBatch(tablesBatch);
        log.info("批次提交，size:{}，status:{}", tablesBatch.size(), batch);
        tablesBatch.clear();
    }

}
